using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using TexasInstruments.Types.Variables;
using System.Reflection;

namespace TexasInstruments.Types {
	public class GroupFile {

		private CalculatorModel model;
		/// <summary>
		/// Gets or sets the calculator model of this group file.
		/// </summary>
		public CalculatorModel Model {
			get { return this.model; }
			set {
				if (!Enum.IsDefined(typeof(CalculatorModel), value)) throw new ArgumentException("Unsupported model.");
				this.model = value;
			}
		}

		public GroupFile(CalculatorModel model) {
			this.model = model;
			this.variables = new List<Variable>();
			this.comment = "Generated by " + Assembly.GetExecutingAssembly().GetName().Name + " " + Assembly.GetExecutingAssembly().GetName().Version.ToString();
		}

		private readonly List<Variable> variables;
		/// <summary>
		/// Gets the list of variables in the group file.
		/// </summary>
		public List<Variable> Variables {
			get { return this.variables; }
		}

		private string comment;
		/// <summary>
		/// Gets or sets the file comment.
		/// </summary>
		public string Comment {
			get { return this.comment; }
			set { this.comment = value; }
		}

		/// <summary>
		/// Save the group file to a stream.
		/// </summary>
		/// <param name="stream">The stream to write to.</param>
		public void Save(Stream stream) {

			BinaryWriter GroupWriter = new BinaryWriter(stream);
			string Signature = null;
			
			switch (this.Model) {
				case CalculatorModel.TI83Plus:
					Signature = "**TI83F*";
					break;
				case CalculatorModel.TI83:
					Signature = "**TI83**";
					break;
				case CalculatorModel.TI82:
					Signature = "**TI82**";
					break;
				case CalculatorModel.TI86:
					Signature = "**TI86**";
					break;
				case CalculatorModel.TI85:
					Signature = "**TI85**";
					break;
				case CalculatorModel.TI73:
					Signature = "**TI73**";
					break;
					
			}
			GroupWriter.Write(Encoding.ASCII.GetBytes(Signature));

			// 3-byte signature.
			GroupWriter.Write((byte)0x1A);
			GroupWriter.Write(this.Model == CalculatorModel.TI85 ? (byte)0x0C : (byte)0x0A);
			GroupWriter.Write((byte)0x00);

			// 42-byte comment.
			GroupWriter.Write(Encoding.ASCII.GetBytes(this.Comment.PadRight(43, '\0').Remove(42)));
			
			// Create output data;
			MemoryStream AllVariables = new MemoryStream(1024);
			foreach (Variable V in this.Variables) {
				V.Save(AllVariables);
			}
			byte[] VariableData = AllVariables.ToArray();

			// Size:
			GroupWriter.Write((ushort)VariableData.Length);

			// Data:
			GroupWriter.Write(VariableData);

			// Checksum:
			ushort Checksum = 0;
			foreach (byte b in VariableData) Checksum += b;
			GroupWriter.Write(Checksum);
		}

	}
}
